﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Configuration;
using System.CodeDom.Compiler;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using QASampling.BusinessObject;
using QASampling.UI;
using QASampling.QAControl;

namespace QASampling.Util
{
    class ValidationUtil
    {
        private const string EMPTY_STRING = "EMPTY";
        internal static bool IsValidCurrency(bool bReformatOrNot, string sValue1, ref string sValue2, bool bCanEmpty)
        {
            try
            {
                sValue2 = string.Empty;
                LogUtil.WriteLog("Entering IsValidCurrency Method");
                decimal dValue1 = 0;
                bool bReturn = true;
                NumberStyles styles = NumberStyles.AllowParentheses | NumberStyles.AllowThousands | NumberStyles.AllowDecimalPoint | NumberStyles.AllowCurrencySymbol | NumberStyles.AllowLeadingSign;
                LogUtil.WriteLog("sValue1 1st= " + sValue1);

                //===========modified by Vincent 20120625==============
                if (sValue1.Trim().Equals(""))
                {
                    if (bCanEmpty)
                    {
                        LogUtil.WriteLog("Empty field allowed");
                        bReturn = true;
                    }
                    else
                    {
                        LogUtil.WriteLog("Empty field not allowed");
                        bReturn = false;
                    }
                }
                //=====================================================
                else if (!decimal.TryParse(sValue1, styles, CultureInfo.GetCultureInfo("id-ID"), out dValue1))
                {
                    LogUtil.WriteLog("this is not a currency");
                    bReturn = false;

                    if (bReformatOrNot)
                    {
                        LogUtil.WriteLog("reformat values");
                        if (!string.IsNullOrEmpty(sValue1))
                        {
                            char[] arr = sValue1.ToCharArray();
                            arr = Array.FindAll<char>(arr, (c => (char.IsDigit(c) || c == '(') || c == '-' || c == '.' || c == ',' || c == ')'));
                            sValue1 = new string(arr);

                            if (sValue1.LastIndexOf("(") > 0)
                                sValue1 = sValue1.Substring(sValue1.LastIndexOf("("));

                            int iLastIndex = sValue1.IndexOf(")");
                            if (iLastIndex > -1 && iLastIndex != sValue1.Length - 1)
                                sValue1 = sValue1.Remove(iLastIndex + 1);
                        }
                        LogUtil.WriteLog("sValue1 2nd= " + sValue1);

                        if (!decimal.TryParse(sValue1, styles, CultureInfo.GetCultureInfo("id-ID"), out dValue1))
                        {
                            LogUtil.WriteLog("this is not a currency after reformat");
                            bReturn = false;
                        }
                        else
                        {
                            LogUtil.WriteLog("this is a currency after reformat");
                            bReturn = true;
                        }
                        sValue2 = Convert.ToString(dValue1);
                    }
                }
                else
                {
                    LogUtil.WriteLog("this is a currency");
                    bReturn = true;
                    sValue2 = Convert.ToString(dValue1);
                }
                LogUtil.WriteLog("bReturn = " + bReturn);
                return bReturn;
            }
            catch (Exception ex)
            {
                LogUtil.WriteLog("Exception encountered while executing IsValidCurrency method: " + ex.Message);
                return false;
            }
        }

        internal static bool IsValidCurrency(string sValue1, bool bCanEmpty)
        {
            try
            {
                string value = string.Empty;
                return IsValidCurrency(false, sValue1, ref value, bCanEmpty);
            }
            catch (Exception ex)
            {
                LogUtil.WriteLog("Exception encountered while executing IsValidCurrency method: " + ex.Message);
                return false;
            }
        }

        internal static bool IsValidDateToDBFormat(string sValue1, ref string sValue2, string sDateFormat)
        {
            LogUtil.WriteLog("--- Enter Method: IsValidDate ---");
            try
            {
                string dbdateformat = ConfigurationManager.AppSettings["DBDateFormat"];
                return IsValidDate(sValue1, ref sValue2, sDateFormat, dbdateformat);
            }
            catch (Exception ex)
            {
                LogUtil.WriteLog("Exception encountered while executing IsValidDate method: " + ex.Message);
                return false;
            }
            finally
            {
                LogUtil.WriteLog("--- End Method: IsValidDate ---");
            }
        }

        internal static bool IsValidDate(string sValue1, ref string sValue2, string sDateFormat, string sToDateFormat)
        {
            LogUtil.WriteLog("--- Enter Method: IsValidDate ---");
            try
            {
                string dateFormat = string.Empty;
                if (string.IsNullOrEmpty(sDateFormat))
                {
                    dateFormat = ConfigurationManager.AppSettings["DateFormat"];
                }
                else
                {
                    dateFormat = sDateFormat;
                }
                LogUtil.WriteLog("dateFormat = " + dateFormat);
                LogUtil.WriteLog("DBDateFormat = " + sToDateFormat);

                DateTime dtValue1;
                bool bReturn = true;
                if (!DateTime.TryParseExact(sValue1, dateFormat, null, DateTimeStyles.None, out dtValue1))
                {
                    bReturn = false;
                }
                else
                {
                    sValue2 = dtValue1.ToString(sToDateFormat);
                }
                LogUtil.WriteLog("bReturn = " + bReturn);
                return bReturn;
            }
            catch (Exception ex)
            {
                LogUtil.WriteLog("Exception encountered while executing IsValidDate method: " + ex.Message);
                return false;
            }
            finally
            {
                LogUtil.WriteLog("--- End Method: IsValidDate ---");
            }
        }

        internal static bool IsValidDate(string sValue1, string sDateFormat)
        {
            try
            {
                string value = string.Empty;
                return IsValidDate(sValue1, ref value, sDateFormat, sDateFormat);
            }
            catch (Exception ex)
            {
                LogUtil.WriteLog("Exception encountered while executing IsValidDate method: " + ex.Message);
                return false;
            }
            finally
            {
                LogUtil.WriteLog("--- End Method: IsValidDate ---");
            }
        }

        internal static bool CalculateFieldsMathExp(Control userCtl, string sExpression, ref string errorMsg)
        {
            LogUtil.WriteLog("--- Enter Method: CalculateFieldsMathExp ---");

            if (string.IsNullOrEmpty(sExpression))
                return true;

            //deklarasi regex untuk mengenali SmartParameter
            Regex rgxSmartParam = new Regex(@"[@]+[a-zA-Z0-9\\_.]*");

            //deklarasi regular expression
            Regex rgxMinus = new Regex("[(]+[0-9.]+[)]");

            //deklarasi regular expression
            Regex rgxFunction = new Regex("[[][(\'](.*?)[\')][]]");

            //----Added by Vincent 20130121 for handling word==word-----
            Regex rgxAlphabetics = new Regex(@"[a-zA-Z']+[==]+[a-zA-Z'](?:(?!\)|\(|&&|\|\|).)*");
            //----------------------------------------------------------

            LogUtil.WriteLog("sParam = " + sExpression);
            try
            {
                // hitung sum
                Regex rgxFindSum = new Regex(@"[Ss][Uu][Mm][(][@]+[(a-zA-Z0-9\\._]+[)]");
                string sParamAfterSum = rgxFindSum.Replace(sExpression, delegate(Match match)
                {
                    string v = match.ToString();
                    v = v.Substring(v.IndexOf('(') + 2, v.Length - 6);
                    return SumColumn(userCtl, v);
                });

                // hitung sum with
                Regex rgxFindSumField = new Regex(@"[Ss][Uu][Mm][Ww][Ii][Tt][Hh][(][@]+[(a-zA-Z0-9\\._,;]+[)]");
                sParamAfterSum = rgxFindSumField.Replace(sParamAfterSum, delegate(Match match)
                {
                    string v = match.ToString();
                    v = v.Substring(v.IndexOf('(') + 2, v.Length - 10);
                    string[] arrV = v.Split(';');
                    if (arrV.Length == 4)
                        return SumColumnWithCondition(userCtl, 0, 2, arrV[0], arrV[1], arrV[2], arrV[3]);
                    else
                        return "none";
                });

                String expAfterConvertSmartParam = rgxSmartParam.Replace(sParamAfterSum, delegate(Match match)
                {
                    string v = match.ToString();
                    string tempSmartParam = v.Substring(1, v.Length - 1);
                    LogUtil.WriteLog("Found smart parameter = " + tempSmartParam);
                    string tempResultSmartParam = string.Empty;
                    if (tempSmartParam.Contains("."))
                    {
                        Control formSearch = GetControl(userCtl, tempSmartParam);
                        tempSmartParam = tempSmartParam.Split('.').Last();
                        //tempResultSmartParam = GetFieldValue(formSearch, tempSmartParam) edited by Vincent 20130201 for handle ,
                        tempResultSmartParam = GetFieldValue(formSearch, tempSmartParam).Replace(",",".");
                    }
                    else
                    {
                        Control formSearch = GetControl(userCtl, tempSmartParam);
                        //tempResultSmartParam = GetFieldValue(formSearch, tempSmartParam) edited by Vincent 20130201 for handle ,
                        tempResultSmartParam = GetFieldValue(formSearch, tempSmartParam).Replace(",", ".");
                    }
                    if (string.IsNullOrEmpty(tempResultSmartParam))
                    {
                        LogUtil.WriteLog("Assign value min to smart parameter " + tempSmartParam);
                        return "(" + decimal.MinValue + ")";
                    }
                    else
                    {
                        LogUtil.WriteLog("Get value smart param " + tempSmartParam + " = " + tempResultSmartParam);
                        return tempResultSmartParam;
                    }
                });

                // get label for field

                string labelTextSmartParam = rgxFindSumField.Replace(sExpression, delegate(Match match)
                {
                    string v = match.ToString();
                    v = v.Substring(v.IndexOf('(') + 1, v.Length - 9);
                    string[] arrV = v.Split(';');
                    if (arrV.Length == 4)
                        return "Jumlah kolom " + arrV[3] + " pada " + arrV[0] + " dengan nilai awal " + arrV[1] + " di kolom " + arrV[2];
                    else
                        return "none";
                });

                labelTextSmartParam = rgxSmartParam.Replace(labelTextSmartParam, delegate(Match match)
                {
                    string v = match.ToString();
                    string tempSmartParam = v.Substring(1, v.Length - 1);
                    string tempResultSmartParam = string.Empty;
                    if (tempSmartParam.Contains("."))
                    {
                        Control formSearch = GetControl(userCtl, tempSmartParam);
                        tempSmartParam = tempSmartParam.Split('.').Last();
                        tempResultSmartParam = GetFieldLabelText(formSearch, tempSmartParam);
                    }
                    else
                    {
                        Control formSearch = GetControl(userCtl, tempSmartParam);
                        if (tempSmartParam.ToUpper().Equals(EMPTY_STRING))
                            return EMPTY_STRING;
                        tempResultSmartParam = GetFieldLabelText(formSearch, tempSmartParam);
                    }
                    LogUtil.WriteLog("Found smart parameter = " + tempSmartParam);
                    LogUtil.WriteLog("Get label smart param " + tempSmartParam + " = " + tempResultSmartParam);
                    return tempResultSmartParam + Environment.NewLine;
                });

                labelTextSmartParam = labelTextSmartParam.Replace("&&", " dan ");
                labelTextSmartParam = labelTextSmartParam.Replace("||", " atau ");
                labelTextSmartParam = labelTextSmartParam.Replace("!", " tidak ");
                labelTextSmartParam = labelTextSmartParam.Replace("EMPTY", " boleh kosong : ");
                labelTextSmartParam = labelTextSmartParam.Replace("['", "");
                labelTextSmartParam = labelTextSmartParam.Replace("\']", "");
                labelTextSmartParam = labelTextSmartParam.Replace("SUM", " penjumlahan field ");

                //lihat hasil convert Smart Parameter
                LogUtil.WriteLog("Expression after smart parameter = " + expAfterConvertSmartParam);

                //Mengubah hanya semua angka tanpa operasi matematika dalam tanda kurung menjadi minus
                String expAfterConvertMinus = rgxMinus.Replace(expAfterConvertSmartParam, delegate(Match match)
                {
                    string v = match.ToString();
                    return "-" + v.Substring(v.IndexOf('(') + 1, v.Length - 2);
                });

                //lihat hasil convert minus
                LogUtil.WriteLog("Expression after convert currency = " + expAfterConvertMinus);

                //giving m to others
                //modified by Vincent 20130204 for handling modulus for ppn tolerance------------------------------------------------------
                //string[] parts = Regex.Split(new StringBuilder(expAfterConvertMinus).Replace(" ", "").ToString(), @"([-*/<>!=+()|&])");
                string[] parts = Regex.Split(new StringBuilder(expAfterConvertMinus).Replace(" ", "").ToString(), @"([-*/%<>!=+()|&])");
                //-----------------------------------------------------------------------------------------------------------------------
                string expFinal = "";
                foreach (string part in parts)
                {
                    if (IsValidCurrency(part, false))
                    {
                        expFinal += (part + "m");
                    }
                    else
                    {
                        expFinal += part;
                    }
                }

                // convert EMPTY
                expFinal = expFinal.Replace(EMPTY_STRING, "string.IsNullOrEmpty");
                expFinal = rgxFunction.Replace(expFinal, delegate(Match match)
                {
                    string v = match.ToString();
                    v = v.Substring(v.IndexOf('\'') + 1, v.Length - 4);
                    return "(\"" + v + "\")";
                });

                // convert null value
                expFinal = expFinal.Replace("\"(" + decimal.MinValue + "m)\"", "\"\"");
                expFinal = expFinal.Replace("" + decimal.MinValue + "m", "0m");

                //replace = to == except >= <= and !=
                string[] splitoperand = Regex.Split(expFinal, @"([|&])");
                expFinal = string.Empty;
                foreach (string s in splitoperand)
                {
                    string[] temp = s.Split('=');
                    string temp1 = s;
                    if (temp[0].IndexOf(">") == -1 && temp[0].IndexOf("<") == -1 && temp[0].IndexOf("!") == -1)
                    {
                        temp1 = s.Replace("=", "==");
                    }
                    expFinal += temp1;
                }

                //----Added by Vincent 20130121 for handling word==word-----
                expFinal = rgxAlphabetics.Replace(expFinal, delegate(Match match)
                {
                    string v = match.ToString();
                    string[] ar = { "==" };
                    string[] split = v.Split(ar, StringSplitOptions.RemoveEmptyEntries);
                    if (split[0].Equals(split[1]))
                    {
                        //word1 equals with word2
                        return "1==1";
                    }
                    else
                    {
                        //word1 not equals with word2
                        return "0==1";
                    }
                });
                //----------------------------------------------------------

                LogUtil.WriteLog("Final expression = " + expFinal);

                //added by Vincent 20130207 for handling -- to +
                expFinal = expFinal.Replace("--","+");
                //-------------------------------------

                bool b;
                try
                {
                    bool result = EvaluateExpression(expFinal);
                    errorMsg = labelTextSmartParam;
                    LogUtil.WriteLog(result + "");
                    return result;
                }
                catch (Exception)
                {
                    //not valid boolean expression
                    LogUtil.WriteLog("Error expression");
                    errorMsg = "Error expression";
                    return false;
                }
            }
            catch (Exception ex)
            {
                LogUtil.WriteLog("Exception encountered while executing CalculateFieldsMathExp method: " + ex.Message);
                return false;
            }
            finally
            {
                LogUtil.WriteLog("--- End Method: CalculateFieldsMathExp ---");
            }
        }

        internal static bool CalculateGrid(DataGridViewRow row, string sExpression, string[] labelText, ref string errorMsg)
        {
            LogUtil.WriteLog("--- Enter Method: CalculateGrid ---");

            if (string.IsNullOrEmpty(sExpression))
                return true;

            //deklarasi regex untuk mengenali SmartParameter
            Regex rgxSmartParam = new Regex(@"[@]+[a-zA-Z0-9\\_.]*");

            //deklarasi regular expression
            Regex rgxMinus = new Regex("[(]+[0-9.]+[)]");

            //deklarasi regular expression
            Regex rgxFunction = new Regex("[[][(\'](.*?)[\')][]]");

            //----Added by Vincent 20130121 for handling word==word-----
            Regex rgxAlphabetics = new Regex(@"[a-zA-Z']+[==]+[a-zA-Z'](?:(?!\)|\(|&&|\|\|).)*");
            //----------------------------------------------------------

            LogUtil.WriteLog("sParam = " + sExpression);
            try
            {   
                String expAfterConvertSmartParam = rgxSmartParam.Replace(sExpression, delegate(Match match)
                {
                    string v = match.ToString();
                    string tempSmartParam = v.Substring(1, v.Length - 1);
                    LogUtil.WriteLog("Found smart parameter = " + tempSmartParam);
                    string tempResultSmartParam = string.Empty;
                    tempResultSmartParam = row.Cells[tempSmartParam].Value.ToString().Replace(",", ".");
                    
                    if (string.IsNullOrEmpty(tempResultSmartParam))
                    {
                        LogUtil.WriteLog("Assign value min to smart parameter " + tempSmartParam);
                        return "(" + decimal.MinValue + ")";
                    }
                    else
                    {
                        LogUtil.WriteLog("Get value smart param " + tempSmartParam + " = " + tempResultSmartParam);
                        return tempResultSmartParam;
                    }
                });

                // get label for field
                string labelTextSmartParam = rgxSmartParam.Replace(sExpression, delegate(Match match)
                {
                    string v = match.ToString();
                    string tempSmartParam = v.Substring(1, v.Length - 1);
                    string tempResultSmartParam = labelText[row.Cells[tempSmartParam].ColumnIndex];                 
                    return tempResultSmartParam + Environment.NewLine;
                });

                labelTextSmartParam = labelTextSmartParam.Replace("&&", " dan ");
                labelTextSmartParam = labelTextSmartParam.Replace("||", " atau ");
                labelTextSmartParam = labelTextSmartParam.Replace("!", " tidak ");
                labelTextSmartParam = labelTextSmartParam.Replace("EMPTY", " boleh kosong : ");
                labelTextSmartParam = labelTextSmartParam.Replace("['", "");
                labelTextSmartParam = labelTextSmartParam.Replace("\']", "");
                labelTextSmartParam = labelTextSmartParam.Replace("SUM", " penjumlahan field ");

                //lihat hasil convert Smart Parameter
                LogUtil.WriteLog("Expression after smart parameter = " + expAfterConvertSmartParam);

                //Mengubah hanya semua angka tanpa operasi matematika dalam tanda kurung menjadi minus
                String expAfterConvertMinus = rgxMinus.Replace(expAfterConvertSmartParam, delegate(Match match)
                {
                    string v = match.ToString();
                    return "-" + v.Substring(v.IndexOf('(') + 1, v.Length - 2);
                });

                //lihat hasil convert minus
                LogUtil.WriteLog("Expression after convert currency = " + expAfterConvertMinus);

                //giving m to others
                //modified by Vincent 20130204 for handling modulus for ppn tolerance------------------------------------------------------
                //string[] parts = Regex.Split(new StringBuilder(expAfterConvertMinus).Replace(" ", "").ToString(), @"([-*/<>!=+()|&])");
                string[] parts = Regex.Split(new StringBuilder(expAfterConvertMinus).Replace(" ", "").ToString(), @"([-*/%<>!=+()|&])");
                //-----------------------------------------------------------------------------------------------------------------------
                string expFinal = "";
                foreach (string part in parts)
                {
                    if (IsValidCurrency(part, false))
                    {
                        expFinal += (part + "m");
                    }
                    else
                    {
                        expFinal += part;
                    }
                }

                // convert EMPTY
                expFinal = expFinal.Replace(EMPTY_STRING, "string.IsNullOrEmpty");
                expFinal = rgxFunction.Replace(expFinal, delegate(Match match)
                {
                    string v = match.ToString();
                    v = v.Substring(v.IndexOf('\'') + 1, v.Length - 4);
                    return "(\"" + v + "\")";
                });

                // convert null value
                expFinal = expFinal.Replace("\"(" + decimal.MinValue + "m)\"", "\"\"");
                expFinal = expFinal.Replace("" + decimal.MinValue + "m", "0m");

                //replace = to == except >= <= and !=
                string[] splitoperand = Regex.Split(expFinal, @"([|&])");
                expFinal = string.Empty;
                foreach (string s in splitoperand)
                {
                    string[] temp = s.Split('=');
                    string temp1 = s;
                    if (temp[0].IndexOf(">") == -1 && temp[0].IndexOf("<") == -1 && temp[0].IndexOf("!") == -1)
                    {
                        temp1 = s.Replace("=", "==");
                    }
                    expFinal += temp1;
                }

                //----Added by Vincent 20130121 for handling word==word-----
                expFinal = rgxAlphabetics.Replace(expFinal, delegate(Match match)
                {
                    string v = match.ToString();
                    string[] ar = { "==" };
                    string[] split = v.Split(ar, StringSplitOptions.RemoveEmptyEntries);
                    if (split[0].Equals(split[1]))
                    {
                        //word1 equals with word2
                        return "1==1";
                    }
                    else
                    {
                        //word1 not equals with word2
                        return "0==1";
                    }
                });
                //----------------------------------------------------------

                LogUtil.WriteLog("Final expression = " + expFinal);

                //added by Vincent 20130207 for handling -- to +
                expFinal = expFinal.Replace("--", "+");
                //-------------------------------------

                bool b;
                try
                {
                    bool result = EvaluateExpression(expFinal);
                    errorMsg = labelTextSmartParam;
                    LogUtil.WriteLog(result + "");
                    return result;
                }
                catch (Exception)
                {
                    //not valid boolean expression
                    LogUtil.WriteLog("Error expression");
                    errorMsg = "Error expression";
                    return false;
                }
            }
            catch (Exception ex)
            {
                LogUtil.WriteLog("Exception encountered while executing CalculateFieldsMathExp method: " + ex.Message);
                return false;
            }
            finally
            {
                LogUtil.WriteLog("--- End Method: CalculateFieldsMathExp ---");
            }
        }

        // for evaluating expression
        private static bool EvaluateExpression(string expression)
        {
            string code = string.Format  // Note: Use "{{" to denote a single "{"  
            (
                @"public static class Func{{ 
public static bool IsNumeric(string strToCheck)
        {{
            foreach (char chr in strToCheck)
                if (!char.IsNumber(chr)) return false;
            return true;
        }} 
public static bool func(){{ bool answer; 
answer = {0}; 
return answer;}}
}}",
                expression
            );

            CompilerResults compilerResults = CompileScript(code);

            if (compilerResults.Errors.HasErrors)
            {
                throw new InvalidOperationException("Expression has a syntax error.");
            }

            Assembly assembly = compilerResults.CompiledAssembly;
            MethodInfo method = assembly.GetType("Func").GetMethod("func");

            return (bool)method.Invoke(null, null);
        }

        private static CompilerResults CompileScript(string source)
        {
            CompilerParameters parms = new CompilerParameters();

            parms.GenerateExecutable = false;
            parms.GenerateInMemory = true;
            parms.IncludeDebugInformation = false;

            CodeDomProvider compiler = Microsoft.CSharp.CSharpCodeProvider.CreateProvider("CSharp");

            return compiler.CompileAssemblyFromSource(parms, source);
        }

        internal static string ValidatingField(frmQAEdit frmQAEdit)
        {
            string value = string.Empty;
            if (frmQAEdit.FieldType.Equals(JenisField.Currency))            
                IsValidCurrency(true, frmQAEdit.FieldValue, ref value, true);                          
            else if (frmQAEdit.FieldType.Equals(JenisField.Varchar))
                value = frmQAEdit.FieldValue;
            else if (frmQAEdit.FieldType.Equals(JenisField.Datetime))
                IsValidDateToDBFormat(frmQAEdit.FieldValue, ref value, frmQAEdit.DateFormat);
            else if (frmQAEdit.FieldType.Equals(JenisField.Boolean))
            {
                if (BoolParser.GetValue(frmQAEdit.FieldValue) == true) value = "1";
                else if (BoolParser.GetValue(frmQAEdit.FieldValue) == false) value = "0";
            }
            else if (frmQAEdit.FieldType.Equals(JenisField.Number))
                IsNumeric(frmQAEdit.FieldValue, ref value);
            else
                value = frmQAEdit.FieldValue;
            return value;
        }

        internal static void ValidatingField(frmQATable frmQATable)
        {
            for (int i = 0; i < frmQATable.FieldName.Length; i++)
            {
                string value = string.Empty;
                if (frmQATable.FieldType[i].Equals(JenisField.Currency))
                    IsValidCurrency(true, frmQATable.FieldValue[i], ref value, true);
                else if (frmQATable.FieldType[i].Equals(JenisField.Varchar))
                    value = frmQATable.FieldValue[i];
                else if (frmQATable.FieldType[i].Equals(JenisField.Datetime))
                    IsValidDateToDBFormat(frmQATable.FieldValue[i], ref value, frmQATable.DateFormat[i]);
                else if (frmQATable.FieldType[i].Equals(JenisField.Boolean))
                {
                    if (BoolParser.GetValue(frmQATable.FieldValue[i]) == true) value = "1";
                    else if (BoolParser.GetValue(frmQATable.FieldValue[i]) == false) value = "0";
                }
                else if (frmQATable.FieldType[i].Equals(JenisField.Number))
                    IsNumeric(frmQATable.FieldValue[i], ref value);
                else
                    value = frmQATable.FieldValue[i];

                frmQATable.FieldValue[i] = value;
            }
        }

        private static string GetFieldValue(Control form, string fieldName)
        {
            string ret = "none";
            var ctl = from c in form.Controls.OfType<QAControl.QATextEdit>()
                      where ((QAControl.QATextEdit)c).FieldName.Contains(fieldName)
                      orderby c.Name ascending
                      select c;

            QAControl.QATextEdit te = ctl.FirstOrDefault<QAControl.QATextEdit>();

            var ctl2 = from c in form.Controls.OfType<QAControl.QACheckBoxEdit>()
                       where ((QAControl.QACheckBoxEdit)c).FieldName.Contains(fieldName)
                       orderby c.Name ascending
                       select c;

            QAControl.QACheckBoxEdit ce = ctl2.FirstOrDefault<QAControl.QACheckBoxEdit>();

            if (te != null)
                ret = te.FieldValue;
            else if (ce != null)
                ret = Convert.ToInt32(ce.Checked).ToString();

            return ret;
        }

        private static string GetFieldLabelText(Control form, string fieldName)
        {
            string ret = "none";
            var ctl = from c in form.Controls.OfType<QAControl.QATextEdit>()
                      where ((QAControl.QATextEdit)c).FieldName.Contains(fieldName)
                      orderby c.Name ascending
                      select c;

            QAControl.QATextEdit te = ctl.FirstOrDefault<QAControl.QATextEdit>();

            var ctl2 = from c in form.Controls.OfType<QAControl.QACheckBoxEdit>()
                       where ((QAControl.QACheckBoxEdit)c).FieldName.Contains(fieldName)
                       orderby c.Name ascending
                       select c;

            QAControl.QACheckBoxEdit ce = ctl2.FirstOrDefault<QAControl.QACheckBoxEdit>();

            if (form.GetType().Equals(typeof(QADataGridWithButton)))
            {
                if (((QADataGridWithButton)form).Datagrid.Columns[fieldName] != null)
                    ret = ((QADataGridWithButton)form).Datagrid.Columns[fieldName].HeaderText;
                if (((QADataGridWithButton)form).Name == fieldName)
                    ret = ((QADataGridWithButton)form).GridLabel;
            }

            if (te != null)
                ret = te.LabelText;
            else if (ce != null)
                ret = ce.LabelText;
            return ret;
        }

        private static Control GetControl(Control userCtl, string fieldName)
        {
            BaseFormSPTWithHeader form = userCtl.FindForm() as BaseFormSPTWithHeader;
            Control ctl = new Control();
            string[] field = fieldName.Split('.');
            if (field[0].Equals("P"))
            {
                if (form.tabControl1.TabPages.ContainsKey(field[1]))
                    ctl = form.tabControl1.TabPages[field[1]];
            }
            else if (field[0].Equals("D"))
            {
                ctl = form.scSPT.Panel1;
            }
            else if (field[0].Equals("DG"))
            {
                if (userCtl.GetType().Equals(typeof(TabPage)))
                    ctl = userCtl.Controls.Find(field[1], true).FirstOrDefault<Control>();
                else
                    ctl = userCtl.Parent.Parent.Controls.Find(field[1], true).FirstOrDefault<Control>();
            }
            else
            {
                if (!userCtl.GetType().Equals(typeof(TabPage)))
                    ctl = userCtl.Parent.Parent;
            }

            if (field.Length - 2 >= 2)
            {
                List<string> fieldList = field.ToList<string>();
                fieldList.Remove(field[0]);
                fieldList.Remove(field[1]);

                ctl = GetControl(ctl, string.Join(".", fieldList.ToArray()));
            }
            return ctl;
        }

        /// <summary>
        /// Determine if a string in numeric or not.
        /// </summary>
        /// <param name="strToCheck">The string to test</param>
        /// <returns>True if numeric, false otherwise.</returns>
        internal static bool IsNumeric(string strToCheck, ref string value)
        {
            if (string.IsNullOrEmpty(strToCheck))
                return false;
            foreach (char chr in strToCheck)
                if (!char.IsNumber(chr)) return false;
            value = strToCheck;
            return true;
        }

        /// <summary>
        /// Determine if a string in alphabetic or not.
        /// </summary>
        /// <param name="strToCheck">The string to test</param>
        /// <returns>True if alphabetic, false otherwise.</returns>
        internal static bool IsAlphabetic(string strToCheck, ref string value)
        {
            foreach (char chr in strToCheck)
                if (!char.IsLetter(chr)) return false;
            value = strToCheck;
            return true;
        }

        internal static string SumColumn(Control userCtl, string fieldName)
        {
            Control formSearch = GetControl(userCtl, fieldName);

            string field = fieldName.Split('.').Last<string>();
            string ret = "0";
            try
            {
                if (formSearch.GetType().Equals(typeof(QADataGridWithButton)))
                {
                    if (formSearch != null)
                    {
                        QADataGrid dg = ((QADataGridWithButton)formSearch).Datagrid;
                        decimal total = decimal.MinValue;
                        foreach (DataGridViewRow row in dg.Rows)
                        {
                            string value = row.Cells[field].Value.ToString();
                            if (string.IsNullOrEmpty(value))
                                continue;
                            if (total == decimal.MinValue)
                                total = 0;
                            decimal fieldvalue = 0;
                            decimal.TryParse(value, out fieldvalue);
                            total += fieldvalue;
                        }
                        ret = total.ToString();
                    }
                }
            }
            catch (Exception)
            {
                return ret;
            }
            return ret;
        }

        internal static string SumColumnWithCondition(Control userCtl, int iStart, int iLength, string sDataGrid, string sWordList, string sFieldSearch, string sFieldCalculate)
        {
            LogUtil.WriteLog("--- Enter Method: SumColumnWithCondition ---");
            string ret = "0";
            try
            {
                LogUtil.WriteLog("iStart = " + iStart);
                LogUtil.WriteLog("iLength = " + iLength);
                LogUtil.WriteLog("sWOrdList = " + sWordList);
                LogUtil.WriteLog("sFieldSearch = " + sFieldSearch);
                LogUtil.WriteLog("sFieldCalculate = " + sFieldCalculate);

                Control formSearch = GetControl(userCtl, sDataGrid);

                string[] sArrFind = sWordList.Split(',');

                if (formSearch.GetType().Equals(typeof(QADataGridWithButton)))
                {
                    if (formSearch != null)
                    {
                        QADataGrid dg = ((QADataGridWithButton)formSearch).Datagrid;
                        decimal total = decimal.MinValue;
                        foreach (DataGridViewRow row in dg.Rows)
                        {
                            string fieldSearchValue = row.Cells[sFieldSearch].Value.ToString();
                            LogUtil.WriteLog("field search value : " + fieldSearchValue);
                            if (fieldSearchValue != string.Empty && (fieldSearchValue.Length >= (iStart + iLength)))
                            {
                                fieldSearchValue = fieldSearchValue.Substring(iStart, iLength);
                                LogUtil.WriteLog("field search value substring : " + fieldSearchValue);

                                foreach (string sFind in sArrFind)
                                {
                                    LogUtil.WriteLog("string to find = " + sFind);
                                    if (string.Compare(fieldSearchValue, sFind) == 0)
                                    {
                                        string sFieldCalc = row.Cells[sFieldCalculate].Value.ToString();
                                        if (string.IsNullOrEmpty(sFieldCalc))
                                        {
                                            continue;
                                        }
                                        else
                                        {
                                            if (total == decimal.MinValue)
                                                total = 0;
                                            decimal fieldvalue = 0;
                                            decimal.TryParse(sFieldCalc, out fieldvalue);
                                            total += fieldvalue;
                                        }
                                    }
                                }
                            }
                        }
                        ret = total.ToString();
                    }
                }
            }
            catch (Exception ex)
            {
                LogUtil.WriteLog("Exception encountered while executing CalculateFieldForLineItem method: " + ex.Message);
                return ret;
            }
            finally
            {
                LogUtil.WriteLog("--- End Method: SumColumnWithCondition ---");
            }
            return ret;
        }

        internal static string RoundingUpTo(string sValue, int digits, decimal dRound)
        {
            LogUtil.WriteLog("--- Enter Method: RoundingUpTo ---");
            try
            {
                LogUtil.WriteLog("sValue = " + sValue);
                LogUtil.WriteLog("dRound = " + dRound);
                decimal dField = 0;

                if (!decimal.TryParse(sValue, out dField))
                {
                    return sValue;
                }
                if (dField > dRound)
                    dField = Math.Round((dField / dRound), digits, MidpointRounding.AwayFromZero) * dRound;
                LogUtil.WriteLog("dField = " + dField);

                return Convert.ToString(dField);
            }
            catch (Exception ex)
            {
                LogUtil.WriteLog("Exception encountered while executing RoundingUpTo method: " + ex.Message);
                return sValue;
            }
            finally
            {
                LogUtil.WriteLog("--- End Method: RoundingUpTo ---");
            }
        }
    }
}
